package bll

import (
	"fmt"
	"github.com/pkg/errors"
	"jgt-oper/src/model"
	"jgt-oper/src/schema"
	"jgt-oper/src/util"
	"sync"
)

// Park 菜单管理
type Park struct {
	sync.RWMutex
	ParkModel model.IPark `inject:"IPark"`
}

// GetLevelCode 获取分级码
func (a *Park) GetLevelCode(parentID string) (string, error) {
	a.Lock()
	defer a.Unlock()

	items, err := a.ParkModel.QueryByParentIDOrderLevelCode(parentID)
	if err != nil {
		return "", err
	} else if len(items) == 0 {
		if parentID == "" {
			return "01", nil
		}
		item, verr := a.Get(parentID)
		if verr != nil {
			return "", verr
		} else if item == nil {
			return "", errors.New("无效的上级")
		}
		return item.LevelCode + "01", nil
	}

	levelCode := items[0].LevelCode
	root := levelCode[:len(levelCode)-2]
	toValue := func(i int) string {
		if i < 10 {
			return fmt.Sprintf("%s0%d", root, i)
		}
		return fmt.Sprintf("%s%d", root, i)
	}

	for i, l := 1, len(items); i < 100; i++ {
		code := toValue(i)
		if i <= l &&
			items[i-1].LevelCode == code {
			continue
		}
		return code, nil
	}

	return "", errors.New("获取分级码发生错误")
}

// QueryPage 查询分页数据
func (a *Park) QueryPage(params schema.ParkQueryParam, pageIndex, pageSize uint) (int64, []*schema.Park, error) {
	return a.ParkModel.QueryPage(params, pageIndex, pageSize)
}

// QueryTree 查询树形数据
func (a *Park) QueryTree(params schema.ParkSelectParam) ([]map[string]interface{}, error) {
	items, err := a.ParkModel.QuerySelect(params)
	if err != nil {
		return nil, err
	}

	mapItems := make([]map[string]interface{}, len(items))
	for i, item := range items {
		mapItems[i] = util.StructToMap(item)
	}

	treeItems := util.Slice2Tree(mapItems, "record_id", "parent_id")
	return util.ConvertToViewTree(treeItems, "name", "record_id", "record_id"), nil
}

// QueryList 条件查询数据列表
func (a *Park) QueryList(params schema.ParkSelectParam) ([]*schema.ParkSelect, error) {
	return a.ParkModel.QuerySelect(params)
}

// Get 精确查询数据
func (a *Park) Get(recordID string) (*schema.Park, error) {
	return a.ParkModel.Get(recordID)
}

// GetByNameAndType 根据名称及类型精确查询
func (a *Park) GetByNameAndType(name string, ty int) (*schema.ParkSelect, error) {
	ps := schema.ParkSelectParam{
		Name: name,
		Type: ty,
	}
	items, err := a.ParkModel.QuerySelect(ps)
	if err != nil {
		return nil, err
	}
	if len(items) == 1 {
		return items[0], nil
	}
	return nil, fmt.Errorf("未找到正确数据")

}

// Create 创建数据
func (a *Park) Create(item *schema.Park) error {
	return a.ParkModel.Create(item)
}

// Update 更新数据
func (a *Park) Update(recordID string, item *schema.Park) error {
	if item.Type == 10 {
		item.ParentID = ""
	}

	oldItem, err := a.Get(recordID)
	if err != nil {
		return err
	} else if oldItem == nil {
		return errors.New("建筑不存在")
	}

	if item.ParentID == "" {
		item.ParentID = oldItem.ParentID
	}

	if item.Name != oldItem.Name {
		//检查重复
		p := schema.ParkSelectParam{
			Name:     item.Name,
			ParentID: item.ParentID,
			Type:     item.Type,
		}
		ls, _ := a.QueryList(p)
		if len(ls) > 0 {
			return errors.New("建筑已存在")
		}
	}

	// 优先更新分级码
	if item.ParentID != oldItem.ParentID {
		levelCode, verr := a.GetLevelCode(item.ParentID)
		if verr != nil {
			return verr
		}

		verr = a.ParkModel.UpdateLevelCode(oldItem.LevelCode, levelCode)
		if verr != nil {
			return verr
		}
	}

	info := util.StructToMap(item)
	delete(info, "id")
	delete(info, "record_id")
	delete(info, "creator")
	delete(info, "created")
	delete(info, "deleted")
	delete(info, "level_code")

	return a.ParkModel.Update(recordID, info)
}

// UpdateStatus 更新状态
func (a *Park) UpdateStatus(recordID string, status int) error {
	info := map[string]interface{}{
		"status": status,
	}

	return a.ParkModel.Update(recordID, info)
}

// UpdateLeaseStatus 更新租赁状态
func (a *Park) UpdateLeaseStatus(nodeID string, info map[string]interface{}) error {
	return a.ParkModel.Update(nodeID, info)
}

// Delete 删除数据
func (a *Park) Delete(recordID string) error {
	exists, err := a.ParkModel.CheckChild(recordID)
	if err != nil {
		return err
	} else if exists {
		return errors.New("含有下级菜单，不能删除")
	}

	return a.ParkModel.Delete(recordID)
}

// convActionTree 遍历菜单树，将功能的子级转换为动作数组
func (a *Park) convActionTree(child *[]map[string]interface{}) {
	for _, c := range *child {
		if util.TT(c["type"]).Int() == 30 {
			children, ok := c["children"]
			if ok {
				delete(c, "children")
				childActions := *children.(*[]map[string]interface{})
				actions := make([]map[string]interface{}, len(childActions))

				for i, c := range childActions {
					actions[i] = map[string]interface{}{
						"record_id":  c["record_id"],
						"level_code": c["level_code"],
						"code":       c["code"],
						"name":       c["name"],
						"router":     c["router"],
					}
				}

				c["actions"] = actions
			}
			continue
		}

		if children, ok := c["children"]; ok {
			a.convActionTree(children.(*[]map[string]interface{}))
		}
	}
}

// QueryByIDs 根据ID列表查询菜单数据
func (a *Park) QueryByIDs(recordIDs []string) ([]*schema.Park, error) {
	return a.ParkModel.QueryByIDs(recordIDs)
}

// QueryFullName 根据建筑节点record_id查询当前节点的全名
func (a *Park) QueryFullName(nodeRecordID string) (string, error) {
	var (
		park     *schema.Park
		fullName string
		err      error
	)
	//获取建筑节点信息
	park, err = a.Get(nodeRecordID)
	if err != nil { //err != nil 查询失败
		return "", err
	}
	if park == nil {
		return "门牌节点空指针错误...", nil
	}
	//err == nil ,则park != nil
	fullName += "/"
	fullName += park.Name
	//循环查询父节点
	for park.ParentID != "" {
		park, err = a.Get(park.ParentID)
		if err != nil {
			return "", err
		}
		//err == nil ,park 指向新的数据
		fullName = "/" + park.Name + fullName
	}

	return fullName, nil
}

// QueryAllNodes 查询所有的园区和区域信息，作为基础数据，用于前台页面选择框的选择和 根据record_id展示数据
func (a *Park) QueryAllNodes() ([]*schema.Park, error) {
	return a.ParkModel.QueryAllNodes()
}

// QueryAllParentID 查询当前节点的所有父节点
func (a Park) QueryAllParentID(currentNode string, hasCurrent bool) ([]string, error) {
	var (
		park               *schema.Park
		allFathersRecordID []string
		err                error
	)
	allFathersRecordID = make([]string, 0)
	//获取建筑节点信息
	park, err = a.Get(currentNode)
	if err != nil { //err != nil 查询失败
		return nil, err
	}
	//err == nil ,则park != nil
	if hasCurrent {
		allFathersRecordID = append(allFathersRecordID, park.RecordID)
	}
	//循环查询父节点
	for park.ParentID != "" {
		park, err = a.Get(park.ParentID)
		if err != nil {
			return nil, err
		}
		//err == nil ,park 指向新的数据
		allFathersRecordID = append(allFathersRecordID, park.RecordID)
	}

	return allFathersRecordID, nil
}

// QueryAllParentNode 查询指定节点的所有的父节点
func (a Park) QueryAllParentNode(currentNode string, hasCurrent bool) ([]*schema.Park, error) {
	var (
		park          *schema.Park
		allFatherNode []*schema.Park
		err           error
	)
	allFatherNode = make([]*schema.Park, 0)
	//获取建筑节点信息
	park, err = a.Get(currentNode)
	if err != nil { //err != nil 查询失败
		return nil, err
	}
	//err == nil ,则park != nil
	if hasCurrent {
		allFatherNode = append(allFatherNode, park)
	}
	//循环查询父节点
	for park.ParentID != "" {
		park, err = a.Get(park.ParentID)
		if err != nil {
			return nil, err
		}
		//err == nil ,park 指向新的数据
		allFatherNode = append(allFatherNode, park)
	}

	return allFatherNode, nil
}

// QueryChildrenNodes 查询所有子节点(直接子节点和间接子节点)
func (a *Park) QueryChildrenNodes(recordID string) ([]*schema.Park, error) {
	node, err := a.Get(recordID)
	if err != nil { //err != nil 查询失败
		return nil, err
	}
	levelCode := node.LevelCode

	return a.ParkModel.QueryChildrenNodes(levelCode)
}

// QueryDirectChildrenNodes 查询直接子节点
func (a *Park) QueryDirectChildrenNodes(recordID string) ([]*schema.Park, error) {
	return a.ParkModel.QueryDirectChildrenNodes(recordID)
}

// QueryNodesByLevelCode 根据分级码查询节点
func (a *Park) QueryNodesByLevelCode(levelCode string) ([]*schema.Park, error) {
	return a.ParkModel.QueryNodesByLevelCode(levelCode)
}
